#include "type_define.h"

#include <QDateTime>

std::map<uint16_t, std::string> MsgID2Str = {
    {CarAsk, "车辆应答"},
    {CarReg, "车辆注册"},
    {CarAuth, "车辆鉴权"},
    {CarControl, "底盘控制"},
    {CarUpload, "车辆信息汇报"}};

// 车辆基础信息
QDataStream &operator<<(QDataStream &stream, const CarBaseInfo &data)
{
    stream << data.jd << data.wd << data.hb << data.fx
           << data.arg4 << data.arg5 << data.arg6 << data.arg7
           << data.reserve0 << data.reserve1 << data.reserve2 << data.arg8
           << data.arg9 << data.arg10 << data.arg11 << data.reserve3
           << data.reserve4 << data.arg12 << data.arg13 << data.arg14;
    return stream;
}
QDataStream &operator>>(QDataStream &stream, CarBaseInfo &data)
{
    stream >> data.jd >> data.wd >> data.hb >> data.fx
        >> data.arg4 >> data.arg5 >> data.arg6 >> data.arg7
        >> data.reserve0 >> data.reserve1 >> data.reserve2 >> data.arg8
        >> data.arg9 >> data.arg10 >> data.arg11 >> data.reserve3
        >> data.reserve4 >> data.arg12 >> data.arg13 >> data.arg14;
    return stream;
}
QDebug operator<<(QDebug debug, const CarBaseInfo &data)
{
    debug << " 经度:" << data.jd * 1.0 / 1e9 << "°\n"
          << "纬度:" << data.wd * 1.0 / 1e9 << "°\n"
          << "海拔:" << data.hb / (10 * 100.0) << "米\n"
          << "方向:" << data.fx * 0.01 << "°\n"
          << "寻迹方式:" << (data.arg4 ? (data.arg4 == 1 ? "RTK" : (data.arg4 == 2 ? "图像" : "点云")) : "未寻迹") << "\n"
          << "图像寻迹标志位:" << (data.arg5 ? (data.arg5 == 1 ? "图像寻迹中" : "无信号") : "未使用") << "\n"
          << "点云寻迹标志位:" << (data.arg6 ? (data.arg6 == 1 ? "点云寻迹中" : "无信号") : "未使用") << "\n"
          << "RTK标志位:" << (data.arg7 ? (data.arg7 == 1 ? "GPS" : (data.arg7 == 2 ? "DB" : (data.arg7 == 3 ? "RTK-GPS" : (data.arg7 == 4 ? "RTK-BD" : "无信号")))) : "未使用") << "\n"
          << "速度:" << data.arg8 * 0.01 << "m/s\n"
          << "电机转速:" << data.arg9 << "rpm\n"
          << "绕障标志:" << (data.arg10 ? "绕障中" : "未绕障") << "\n"
          << "档位:" << (data.arg11 ? (data.arg11 == 1 ? "D" : "R") : "N") << "\n"
          << "GPS时间:" << QDateTime::fromMSecsSinceEpoch(data.arg12).toString("yyyy-MM-dd hh:mm:ss.zzz") << "\n"
          << "刹车:" << data.arg13 << "\n"
          << "油门:" << data.arg14;
    return debug;
}

// 车辆附加信息
QDataStream &operator<<(QDataStream &stream, const CarSubjoinInfo &data)
{
    uint16_t len = data.items.size();
    for (int i = 0; i < len; i++) {
        const CarSubjoinInfo::SubjoItem &item = data.items[i];
        stream << item.id << item.length;
        switch (item.length) {
        case 1:
            stream << item.value8;
            break;
        case 2:
            stream << item.value16;
            break;
        case 4:
            stream << item.value32;
            break;
        }
    }
    return stream;
}
QDataStream &operator>>(QDataStream &stream, CarSubjoinInfo &data)
{
    data.items.clear();
    while (!stream.atEnd()) {
        CarSubjoinInfo::SubjoItem item;
        stream >> item.id >> item.length;
        switch (item.length) {
        case 1:
            stream >> item.value8;
            break;
        case 2:
            stream >> item.value16;
            break;
        case 4:
            stream >> item.value32;
            break;
        }
        data.items.push_back(item);
    }
    return stream;
}
QDebug operator<<(QDebug debug, const CarSubjoinInfo &data)
{
    uint16_t len = data.items.size();
    for (int i = 0; i < len; i++) {
        const CarSubjoinInfo::SubjoItem &item = data.items[i];
        switch (item.id) {
        case CarSubjoinInfo::ID0: {
            debug << "剩余电量:" << item.value16 << "%\n";
        } break;
        case CarSubjoinInfo::ID1: {
            debug << "车辆状态:";
            switch (item.value8) {
            case 0x14:
                debug << "自动驾驶";
                break;
            case 0x15:
                debug << "人工驾驶";
                break;
            case 0x16:
                debug << "平行驾驶";
                break;
            case 0:
                debug << "未知";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID2: {
            debug << "手刹状态:" << (item.value16 ? (item.value16 == 1 ? "未拉起" : "拉起") : "未知") << "\n";
        } break;
        case CarSubjoinInfo::ID3: {
            debug << "方向盘角度:" << (int16_t)item.value16 << "°\n";
        } break;
        case CarSubjoinInfo::ID4: {
            debug << "任务状态:" << (item.value16 ? (item.value16 == 1 ? "任务执行中" : (item.value16 == 2 ? "任务已结束" : "点云")) : "到达管控区") << "\n";
        } break;
        case CarSubjoinInfo::ID5: {
            debug << "剩余里程:" << item.value16 << "m\n";
        } break;
        case CarSubjoinInfo::ID6: {
            debug << "定位状态:" << (item.value16 ? "有效定位，有无GPS数据" : "无效定位") << "\n";
        } break;
        case CarSubjoinInfo::ID7: {
            debug << "充电状态:" << (item.value16 ? (item.value16 == 1 ? "充电完成" : (item.value16 == 2 ? "充电中" : "电量低，需要充电")) : "无需充电") << "\n";
        } break;
        case CarSubjoinInfo::ID8: {
            debug << "故障信息:\n";
            debug << (item.faultState.arg0 ? "高清相机通信超时或故障\n" : "");
            debug << (item.faultState.arg1 ? "左/右/后侧激光雷达超时或故障\n" : "");
            debug << (item.faultState.arg2 ? "左右前后激光雷达时间同步失败\n" : "");
            debug << (item.faultState.arg3 ? "左右前后激光雷达时间与系统时间不一致\n" : "");
            debug << (item.faultState.arg4 ? "前方毫米波雷达故障\n" : "");
            debug << (item.faultState.arg5 ? "can通信超时\n" : "");
            debug << (item.faultState.arg6 ? "决策规划模块故障\n" : "");
            debug << (item.faultState.arg7 ? "感知模块故障\n" : "");
            debug << (item.faultState.arg8 ? "预测模块故障\n" : "");
            debug << (item.faultState.arg9 ? "控制模块异常\n" : "");
            debug << (item.faultState.arg10 ? "定位输出不可用\n" : "");
            debug << (item.faultState.arg11 ? "RTK/GPS定位结果输出误差大\n" : "");
            debug << (item.faultState.arg12 ? "障碍物报警\n" : "");
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID9: {
            debug << "车体状态:";
            switch (item.value16) {
            case 0:
                debug << "空闲";
                break;
            case 1:
                debug << "忙碌中";
                break;
            case 2:
                debug << "待充电";
                break;
            case 3:
                debug << "充电中";
                break;
            case 4:
                debug << "手动控制";
                break;
            case 5:
                debug << "故障";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID10: {
            debug << "已行进路线点百分比:" << item.value32 * 0.01 << "%\n";
        } break;
        case CarSubjoinInfo::ID11: {
            // TODO:没看懂文档
            debug << "当前动作:" << item.value16 << "\n";
        } break;
        case CarSubjoinInfo::ID12: {
            // TODO:没看懂文档
            debug << "当前路径途径点ID:" << item.value16 << "\n";
        } break;
        case CarSubjoinInfo::ID13: {
            debug << "毫米波雷达:";
            switch (item.value16) {
            case 0:
                debug << "开";
                break;
            case 1:
                debug << "关";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID14: {
            debug << "障碍物:";
            switch (item.value8) {
            case 0:
                debug << "前后都没有障碍物";
                break;
            case 1:
                debug << "前有障碍物";
                break;
            case 2:
                debug << "后有障碍物";
                break;
            case 4:
                debug << "左有障碍物";
                break;
            case 8:
                debug << "右有障碍物";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID15: {
            debug << "车灯控制:\n";
            auto fun = [&](int a) {
                switch (a) {
                case 0:
                    debug << "无动作";
                    break;
                case 1:
                    debug << "开启";
                    break;
                case 3:
                    debug << "关闭";
                    break;
                }
            };
            debug << "左转向灯:";
            fun(BITSVAULE(item.value32, 0, 1));
            debug << "\n";
            debug << "右转向灯:";
            fun(BITSVAULE(item.value32, 2, 3));
            debug << "\n";
            debug << "昼间行车灯:";
            fun(BITSVAULE(item.value32, 4, 5));
            debug << "\n";
            debug << "警示双闪灯:";
            fun(BITSVAULE(item.value32, 6, 7));
            debug << "\n";
            debug << "示宽灯:";
            fun(BITSVAULE(item.value32, 8, 9));
            debug << "\n";
            debug << "大灯:";
            fun(BITSVAULE(item.value32, 10, 11));
            debug << "\n";
            debug << "后雾灯:";
            fun(BITSVAULE(item.value32, 12, 13));
            debug << "\n";
            debug << "左前雾灯:";
            fun(BITSVAULE(item.value32, 14, 15));
            debug << "\n";
            debug << "右前雾灯:";
            fun(BITSVAULE(item.value32, 16, 17));
            debug << "\n";
            debug << "内顶灯:";
            fun(BITSVAULE(item.value32, 18, 19));
            debug << "\n";
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID16: {
            debug << "车内冷暖空调:";
            switch (item.value8) {
            case 0:
                debug << "无动作";
                break;
            case 1:
                debug << "制冷";
                break;
            case 2:
                debug << "制热";
                break;
            case 3:
                debug << "关闭";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID17: {
            debug << "车内空调温度:" << item.value16 << "℃\n";
        } break;
        case CarSubjoinInfo::ID18: {
            debug << "整车故障级别:";
            switch (item.value8) {
            case 0:
                debug << "无故障";
                break;
            case 1:
                debug << "1级故障，轻微故障，警告提示";
                break;
            case 2:
                debug << "2级故障，一般故障，跛行降速行驶";
                break;
            case 3:
                debug << "3级故障，严重故障，转向系统、动力系统失效，立即停车（退出无人驾驶状态）";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID19: {
            debug << "行人提示器状态:";
            switch (item.value8) {
            case 0:
                debug << "行车警示音";
                break;
            case 1:
                debug << "语音提示（车辆靠近请注意）";
                break;
            case 2:
                debug << "行车提示音（叮咚、叮咚）";
                break;
            case 0xFF:
                debug << "关闭提示音";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID20: {
            debug << "当前模式:";
            switch (item.value8) {
            case 0:
                debug << "空闲模式";
                break;
            case 1:
                debug << "点云/RTK遥控获取循迹";
                break;
            case 2:
                debug << "点云/RTK正向循迹";
                break;
            case 3:
                debug << "点云/RTK反向循迹";
                break;
            case 4:
                debug << "图像寻迹";
                break;
            case 0xFF:
                debug << "遥控控制";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID21: {
            debug << "故障信息:\n";
            debug << "整车绝缘故障等级:";
            switch (BITSVAULE(item.value32, 0, 1)) {
            case 0x00:
                debug << "无故障（正常）";
                break;
            case 0x01:
                debug << "一般故障，小于 500Ω/V 且大于 100Ω/V，停车后检查";
                break;
            case 0x02:
                debug << "严重故障，小于 100Ω/V，切断高压，立即检查";
                break;
            }
            debug << "\n";
            debug << "DC 故障状态:";
            switch (BITSVAULE(item.value32, 2, 2)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障，无人驾驶系统供电将受影响，跛行";
                break;
            }
            debug << "\n";
            debug << "SOC 过低故障状态:";
            switch (BITSVAULE(item.value32, 3, 3)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "单体/电池组电压过低故障状态:";
            switch (BITSVAULE(item.value32, 4, 4)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "制动助力压力异常故障状态:";
            switch (BITSVAULE(item.value32, 5, 5)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "真空泵/气泵故障状态:";
            switch (BITSVAULE(item.value32, 6, 6)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "整车系统故障状态:";
            switch (BITSVAULE(item.value32, 7, 7)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "电池过热故障状态:";
            switch (BITSVAULE(item.value32, 8, 8)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "电机过热故障状态:";
            switch (BITSVAULE(item.value32, 9, 9)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "动力电池故障状态:";
            switch (BITSVAULE(item.value32, 10, 10)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "电机故障状态:";
            switch (BITSVAULE(item.value32, 11, 11)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "电池通讯异常故障状态:";
            switch (BITSVAULE(item.value32, 12, 12)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "电机通讯异常故障状态:";
            switch (BITSVAULE(item.value32, 13, 13)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "EPS 故障状态:";
            switch (BITSVAULE(item.value32, 14, 14)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "空调故障状态:";
            switch (BITSVAULE(item.value32, 15, 15)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "12/24 辅助电池异常故障状态:";
            switch (BITSVAULE(item.value32, 16, 16)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "电子手刹故障状态:";
            switch (BITSVAULE(item.value32, 17, 17)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "线控制动系统故障状态:";
            switch (BITSVAULE(item.value32, 18, 18)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "未检测到钥匙故障状态:";
            switch (BITSVAULE(item.value32, 19, 19)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "胎压过低故障状态:";
            switch (BITSVAULE(item.value32, 20, 20)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "电池系统故障等级:";
            switch (BITSVAULE(item.value32, 24, 25)) {
            case 0x00:
                debug << "无故障";
                break;
            case 0x01:
                debug << "轻微故障，对应能自动恢复的轻微故障";
                break;
            case 0x02:
                debug << "一般故障，对应能自动恢复的一般故障";
                break;
            case 0x03:
                debug << "严重故障，对应需立即下电的严重故障，需查明原因方可重新上电";
                break;
            }
            debug << "\n";
            debug << "电机系统故障等级:";
            switch (BITSVAULE(item.value32, 26, 27)) {
            case 0x00:
                debug << "无故障";
                break;
            case 0x01:
                debug << "轻微故障，电机需降功率输出";
                break;
            case 0x02:
                debug << "一般故障，电机需停止输出";
                break;
            case 0x03:
                debug << "严重故障，需要断电的严重故障（对应 MCU 协议 3、4 级故障）";
                break;
            }
            debug << "\n";
            debug << "不能进入无人驾驶模式的原因:";
            switch (BITSVAULE(item.value32, 28, 31)) {
            case 0x00:
                debug << "无故障";
                break;
            case 0x01:
                debug << "整车系统故障";
                break;
            case 0x02:
                debug << "无人驾驶系统故障";
                break;
            case 0x03:
                debug << "无人驾驶系统可靠性故障";
                break;
            case 0x04:
                debug << "无人驾驶系统启动状态错误";
                break;
            case 0x05:
                debug << "EPS 命令-校验错误";
                break;
            case 0x06:
                debug << "车速命令-校验错误";
                break;
            case 0x07:
                debug << "失联，发送报文超时";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID22: {
            debug << "驾驶故障:\n";
            debug << "不能进入远程驾驶模式的原因:";
            switch (BITSVAULE(item.value32, 0, 3)) {
            case 0x00:
                debug << "无故障";
                break;
            case 0x01:
                debug << "整车系统故障";
                break;
            case 0x02:
                debug << "远程驾驶系统故障";
                break;
            case 0x03:
                debug << "远程驾驶系统可靠性故障";
                break;
            case 0x04:
                debug << "远程驾驶系统连接状态错误";
                break;
            case 0x05:
                debug << "EPS 命令-校验错误";
                break;
            case 0x06:
                debug << "车速命令-校验错误";
                break;
            case 0x07:
                debug << "失联，发送报文超时";
                break;
            }
            debug << "\n";
            debug << "进入线控驾驶后，线控控制器故障:";
            switch (BITSVAULE(item.value32, 4, 5)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "无人驾驶故障(仅能通过复位按钮清除)";
                break;
            case 0x02:
                debug << "遥控驾驶故障(故障消失后可自行清除)";
                break;
            case 0x03:
                debug << "远程驾驶故障(故障消失后可自行清除)";
                break;
            }
            debug << "\n";
            debug << "点火置空挡提醒:";
            switch (BITSVAULE(item.value32, 6, 6)) {
            case 0x00:
                debug << "不提醒";
                break;
            case 0x01:
                debug << "提醒";
                break;
            }
            debug << "\n";
            debug << "点火踩制动踏板提醒:";
            switch (BITSVAULE(item.value32, 7, 7)) {
            case 0x00:
                debug << "不提醒";
                break;
            case 0x01:
                debug << "提醒";
                break;
            }
            debug << "\n";
            debug << "制动液液位低故障:";
            switch (BITSVAULE(item.value32, 8, 8)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "制动系统漏液故障:";
            switch (BITSVAULE(item.value32, 9, 9)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "车外温度传感器状态:";
            switch (BITSVAULE(item.value32, 10, 10)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
            debug << "车内温度传感器状态:";
            switch (BITSVAULE(item.value32, 11, 11)) {
            case 0x00:
                debug << "正常";
                break;
            case 0x01:
                debug << "故障";
                break;
            }
            debug << "\n";
        } break;
        case CarSubjoinInfo::ID23: {
            debug << "故障状态扩展:\n";
            debug << (item.faultState.arg0 ? "RTK/GPS定位结果输出误差大\n" : "");
            debug << (item.faultState.arg1 ? "高清相机通信超时或故障\n" : "");
            debug << (item.faultState.arg2 ? "双目摄像头超时或故障\n" : "");
            debug << (item.faultState.arg3 ? "双目摄像头被遮挡\n" : "");
            debug << (item.faultState.arg4 ? "左侧激光雷达超时或故障\n" : "");
            debug << (item.faultState.arg5 ? "左侧激光雷达被遮挡\n" : "");
            debug << (item.faultState.arg6 ? "右侧激光雷达超时或故障\n" : "");
            debug << (item.faultState.arg7 ? "右侧激光雷达被遮挡\n" : "");
            debug << (item.faultState.arg8 ? "后方激光雷达超时或故障\n" : "");
            debug << (item.faultState.arg9 ? "后方激光雷达被遮挡\n" : "");
            debug << (item.faultState.arg10 ? "前方毫米波雷达故障\n" : "");
            debug << (item.faultState.arg11 ? "轮速传感器故障\n" : "");
            debug << (item.faultState.arg12 ? "车道线寻迹无法寻迹,没找到车道线目标点\n" : "");
            debug << (item.faultState.arg13 ? "点云寻迹无法寻迹，没找到点云目标点\n" : "");
            debug << (item.faultState.arg14 ? "RTK寻迹无法寻迹，没找到GPS目标点\n" : "");
            debug << (item.faultState.arg15 ? "点云地图加载失败\n" : "");
            debug << (item.faultState.arg16 ? "获取GPS轨迹点失败\n" : "");
            debug << (item.faultState.arg17 ? "超出电子围栏，越界停车\n" : "");
            debug << (item.faultState.arg18 ? "IMU无数据或故障\n" : "");
            debug << (item.faultState.arg19 ? "底盘:转向异常\n" : "");
            debug << (item.faultState.arg20 ? "底盘:档位异常\n" : "");
            debug << (item.faultState.arg21 ? "底盘:油门异常\n" : "");
            debug << (item.faultState.arg22 ? "底盘:刹车异常\n" : "");
            debug << (item.faultState.arg23 ? "底盘:温度异常\n" : "");
            debug << (item.faultState.arg24 ? "底盘:速度异常\n" : "");
            debug << (item.faultState.arg25 ? "NX与主控通讯异常\n" : "");
            debug << (item.faultState.arg26 ? "语音播报/声光报警异常\n" : "");
            debug << "\n";
        } break;
        }
    }

    return debug;
}
// 车辆信息
QDataStream &operator<<(QDataStream &stream, const CarInfoBody &data)
{
    stream << data.carBaseInfo << data.carSubjoinInfo;
    return stream;
}
QDataStream &operator>>(QDataStream &stream, CarInfoBody &data)
{
    stream >> data.carBaseInfo >> data.carSubjoinInfo;
    return stream;
}
QDebug operator<<(QDebug debug, const CarInfoBody &data)
{
    debug << "车辆基础信息:\n"
          << data.carBaseInfo;
    debug << "\n车辆附加信息:\n"
          << data.carSubjoinInfo;
    return debug;
}

// MsgHead
QDataStream &operator<<(QDataStream &stream, const MsgHead &data)
{
    stream << data.version << data.msgID << data.msgNum << data.carID << data.reserve;
    return stream;
}
QDataStream &operator>>(QDataStream &stream, MsgHead &data)
{
    stream >> data.version >> data.msgID >> data.msgNum >> data.carID >> data.reserve;
    return stream;
}
QDebug operator<<(QDebug debug, const MsgHead &data)
{
    return debug;
}

// MsgCarAuthBody
QDataStream &operator<<(QDataStream &stream, const MsgCarAuthBody &data)
{
    for (auto i = 0; i < data.authCode.length(); ++i) {
        stream << (uint8_t)data.authCode.at(i).toLatin1();
    }
    return stream;
}
QDataStream &operator>>(QDataStream &stream, MsgCarAuthBody &data)
{
    data.authCode = "";
    uint8_t ch;
    while (!stream.atEnd()) {
        stream >> ch;
        data.authCode += ch;
    }
    return stream;
}
QDebug operator<<(QDebug debug, const MsgCarAuthBody &data)
{
    debug << "鉴权码:" << data.authCode << "\n";
    return debug;
}

// MsgCarControlBody
QDataStream &operator<<(QDataStream &stream, const MsgCarControlBody &data)
{
    uint16_t len = data.cmds.size();
    stream << len;
    for (int i = 0; i < len; i++) {
        const MsgCarControlBody::Cmd &cmd = data.cmds[i];
        stream << cmd.id << cmd.len << cmd.value_word;
    }
    return stream;
}
QDataStream &operator>>(QDataStream &stream, MsgCarControlBody &data)
{
    uint16_t len;
    stream >> len;
    data.cmds.clear();
    for (int i = 0; i < len; i++) {
        MsgCarControlBody::Cmd cmd;
        stream >> cmd.id >> cmd.len >> cmd.value_word;
        data.cmds.push_back(cmd);
    }
    return stream;
}
QDebug operator<<(QDebug debug, const MsgCarControlBody &data)
{
    for (size_t i = 0; i < data.cmds.size(); i++) {
        const MsgCarControlBody::Cmd &cmd = data.cmds[i];
        switch (cmd.id) {
        case 0x00000001:
            debug << "刹车行程:" << cmd.value_int16 << "%\n";
            break;
        case 0x00000052:
            debug << "油门控制:" << cmd.value_word << "%\n";
            break;
        default:
            debug << "cmd id:" << QString("%1").arg(cmd.id, 8, 16, QLatin1Char('0')) << "\n";
            break;
        }
    }
    return debug;
}

// MsgCarAskBody
QDataStream &operator<<(QDataStream &stream, const MsgCarAskBody &data)
{
    stream << data.askNum << data.askID << data.result;
    return stream;
}
QDataStream &operator>>(QDataStream &stream, MsgCarAskBody &data)
{
    stream >> data.askNum >> data.askID >> data.result;
    return stream;
}
QDebug operator<<(QDebug debug, const MsgCarAskBody &data)
{
    debug << "应答流水号:" << data.askNum << ",应答ID:" << data.askID << ",结果:" << data.result << "\n";
    return debug;
}

// MsgGenAskBody
QDataStream &operator<<(QDataStream &stream, const MsgGenAskBody &data)
{
    stream << data.askNum << data.askID << data.result;
    return stream;
}
QDataStream &operator>>(QDataStream &stream, MsgGenAskBody &data)
{
    stream >> data.askNum >> data.askID >> data.result;
    return stream;
}
QDebug operator<<(QDebug debug, const MsgGenAskBody &data)
{
    debug << "应答流水号:" << data.askNum << ",应答ID:" << data.askID << ",结果:" << data.result << "\n";
    return debug;
}

// MSG
QDataStream &operator<<(QDataStream &stream, const Msg &data)
{
    // 封装消息头
    stream << data.msgHead;
    // 封装消息体
    switch (data.msgHead.msgID) {
    case CarAuth: {
        stream << data.carAuthBody;
    } break;
    case CarControl: {
        stream << data.carControlBody;
    } break;
    case CarAsk: {
        stream << data.carAskBody;
    } break;
    case GenAsk: {
        stream << data.genAskBody;
    } break;
    default:
        break;
    }
    return stream;
}
QDataStream &operator>>(QDataStream &stream, Msg &data)
{
    // 获取消息头
    stream >> data.msgHead;
    // 获取消息体
    switch (data.msgHead.msgID) {
    case CarAuth: {
        stream >> data.carAuthBody;
    } break;
    case CarControl: {
        stream >> data.carControlBody;
    } break;
    case CarUpload: {
        stream >> data.carInfoBody;
    } break;
    case CarAsk: {
        stream >> data.carAskBody;
    } break;
    case GenAsk: {
        stream >> data.genAskBody;
    } break;
    default:
        qWarning() << "msg id:" << QString("%1").arg(data.msgHead.msgID, 4, 16, QLatin1Char('0'));
        break;
    }
    return stream;
}
QDebug operator<<(QDebug debug, const Msg &data)
{
    debug << "========printMsg========\n";
    debug << MsgID2Str[data.msgHead.msgID].c_str() << "\n";
    switch (data.msgHead.msgID) {
    case CarAuth: {
        debug << data.carAuthBody << "\n";
    } break;
    case CarControl: {
        debug << data.carControlBody << "\n";
    } break;
    case CarUpload: {
        debug << data.carInfoBody << "\n";
    } break;
    case CarAsk: {
        debug << data.carAskBody;
    } break;
    case GenAsk: {
        debug << data.genAskBody;
    } break;
    default:
        debug << "msg id:" << QString("%1").arg(data.msgHead.msgID, 4, 16, QLatin1Char('0')) << "\n";
        break;
    }
    debug << "========================\n";
    return debug;
}